
package com.yuan.adapt;

import com.yuan.graduate.R;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

/**
 * 抄自系统源码 ResolveActivity.java
 * 
 * @author amen
 */
public class ResolveListAdapter extends BaseAdapter {

    private Intent mIntent;
    private LayoutInflater mInflater;
    private PackageManager mPm;
    private List<DisplayResolveInfo> mList;

    public ResolveListAdapter(Context context, Intent intent,
            Intent[] initialIntents, List<ResolveInfo> rList) {
        mPm = context.getPackageManager();
        mIntent = new Intent(intent);
        mIntent.setComponent(null);
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (rList == null) {
            rList = mPm.queryIntentActivities(
                    intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
        }
        int N;
        if ((rList != null) && ((N = rList.size()) > 0)) {
            ResolveInfo r0 = rList.get(0);
            for (int i = 1; i < N; i++) {
                ResolveInfo ri = rList.get(i);
                if (r0.priority != ri.priority ||
                        r0.isDefault != ri.isDefault) {
                    while (i < N) {
                        rList.remove(i);
                        N--;
                    }
                }
            }
            if (N > 1) {
                ResolveInfo.DisplayNameComparator rComparator =
                        new ResolveInfo.DisplayNameComparator(mPm);
                Collections.sort(rList, rComparator);
            }

            mList = new ArrayList<DisplayResolveInfo>();

            // First put the initial items at the top.
            if (initialIntents != null) {
                for (int i = 0; i < initialIntents.length; i++) {
                    Intent ii = initialIntents[i];
                    if (ii == null) {
                        continue;
                    }
                    ActivityInfo ai = ii.resolveActivityInfo(
                            mPm, 0);
                    if (ai == null) {
                        continue;
                    }
                    ResolveInfo ri = new ResolveInfo();
                    ri.activityInfo = ai;
                    if (ii instanceof LabeledIntent) {
                        LabeledIntent li = (LabeledIntent) ii;
                        ri.resolvePackageName = li.getSourcePackage();
                        ri.labelRes = li.getLabelResource();
                        ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                        ri.icon = li.getIconResource();
                    }
                    CharSequence loadLabel = ri.loadLabel(mPm);
                    if (!isExistTheSameName(new DisplayResolveInfo(ri, loadLabel, null, ii), mList))
                    {
                        mList.add(new DisplayResolveInfo(ri, loadLabel, null, ii));
                    }

                }
            }

            r0 = rList.get(0);
            int start = 0;
            CharSequence r0Label = r0.loadLabel(mPm);
            for (int i = 1; i < N; i++) {
                if (r0Label == null) {
                    r0Label = r0.activityInfo.packageName;
                }
                ResolveInfo ri = rList.get(i);
                CharSequence riLabel = ri.loadLabel(mPm);
                if (riLabel == null) {
                    riLabel = ri.activityInfo.packageName;
                }
                if (riLabel.equals(r0Label)) {
                    continue;
                }
                processGroup(rList, start, (i - 1), r0, r0Label);
                r0 = ri;
                r0Label = riLabel;
                start = i;
            }
            processGroup(rList, start, (N - 1), r0, r0Label);
        }

    }

    /**
     * 判断队列中是否已经存在该应用
     * 
     * @author yuanwei-iri
     * @param displayResolveInfo
     * @param mList2
     * @return
     */
    private boolean isExistTheSameName(DisplayResolveInfo displayResolveInfo,
            List<DisplayResolveInfo> mList2) {
        // TODO Auto-generated method stub
        Iterator<DisplayResolveInfo> it = mList2.iterator();
        while (it.hasNext())
        {
            DisplayResolveInfo temp = it.next();
            if (temp.displayLabel.equals(displayResolveInfo.displayLabel))
            {
                return true;
            }
        }
        return false;
    }

    private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro,
            CharSequence roLabel) {
        // Process labels from start to i
        int num = end - start + 1;
        if (num == 1) {
            // No duplicate labels. Use label for entry at start
            if (!isExistTheSameName(new DisplayResolveInfo(ro, roLabel, null, null), mList))
            {
                mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
            }
        } else {
            boolean usePkg = false;
            CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
            if (startApp == null) {
                usePkg = true;
            }
            if (!usePkg) {
                // Use HashSet to track duplicates
                HashSet<CharSequence> duplicates =
                        new HashSet<CharSequence>();
                duplicates.add(startApp);
                for (int j = start + 1; j <= end; j++) {
                    ResolveInfo jRi = rList.get(j);
                    CharSequence jApp = jRi.activityInfo.applicationInfo.loadLabel(mPm);
                    if ((jApp == null) || (duplicates.contains(jApp))) {
                        usePkg = true;
                        break;
                    } else {
                        duplicates.add(jApp);
                    }
                }
                // Clear HashSet for later use
                duplicates.clear();
            }
            for (int k = start; k <= end; k++) {
                ResolveInfo add = rList.get(k);
                if (usePkg) {
                    // Use application name for all entries from start to end-1

                    if (!isExistTheSameName(new DisplayResolveInfo(add, roLabel,
                            add.activityInfo.packageName, null), mList))
                    {
                        mList.add(new DisplayResolveInfo(add, roLabel,
                                add.activityInfo.packageName, null));
                    }

                } else {
                    // Use package name for all entries from start to end-1
                    if (!isExistTheSameName(new DisplayResolveInfo(add, roLabel,
                            add.activityInfo.applicationInfo.loadLabel(mPm), null), mList))
                    {
                        mList.add(new DisplayResolveInfo(add, roLabel,
                                add.activityInfo.applicationInfo.loadLabel(mPm), null));
                    }

                }
            }
        }
    }

    public ResolveInfo resolveInfoForPosition(int position) {
        if (mList == null) {
            return null;
        }

        return mList.get(position).ri;
    }

    public Intent intentForPosition(int position) {
        if (mList == null) {
            return null;
        }

        DisplayResolveInfo dri = mList.get(position);

        Intent intent = new Intent(dri.origIntent != null
                ? dri.origIntent : mIntent);
        // Bug 78913 - [v5.4.0_build746]分享时选择来往好友，分享内容无法带入
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        ActivityInfo ai = dri.ri.activityInfo;
        intent.setComponent(new ComponentName(
                ai.applicationInfo.packageName, ai.name));
        return intent;
    }

    public int getCount() {
        return mList != null ? mList.size() : 0;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        if (convertView == null) {
            view = mInflater.inflate(
                    R.layout.resolve_list_item, parent, false);
        } else {
            view = convertView;
        }
        bindView(view, mList.get(position));
        return view;
    }

    private final void bindView(View view, DisplayResolveInfo info) {
        TextView text = (TextView) view.findViewById(R.id.text1);
        ImageView icon = (ImageView) view.findViewById(R.id.icon);
        text.setText(info.displayLabel);
        if (info.displayIcon == null) {
            info.displayIcon = info.ri.loadIcon(mPm);
        }
        icon.setImageDrawable(info.displayIcon);
    }

    public final class DisplayResolveInfo {
        ResolveInfo ri;
        CharSequence displayLabel;
        Drawable displayIcon;
        CharSequence extendedInfo;
        Intent origIntent;

        DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
                CharSequence pInfo, Intent pOrigIntent) {
            ri = pri;
            displayLabel = pLabel;
            extendedInfo = pInfo;
            origIntent = pOrigIntent;
        }
    }

    public DisplayResolveInfo displayResolveInfoForPosition(int position) {
        if (mList == null) {
            return null;
        }
        return mList.get(position);
    }

}
